# 报告生成模块
import os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import base64
from io import BytesIO
import sys
sys.path.append('..')
from config import DATA_PATH

class ReportGenerator:
    def __init__(self):
        pass
    
    def generate_price_chart(self, df, days=30):
        """生成价格走势图"""
        # 确保数据按日期排序
        df = df.sort_values('trade_date')
        
        # 获取最近days天的数据
        recent_data = df.iloc[-days:] if len(df) > days else df
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        
        # 绘制K线图
        plt.plot(recent_data['trade_date'], recent_data['close'], label='收盘价')
        plt.plot(recent_data['trade_date'], recent_data['ma5'], label='MA5')
        plt.plot(recent_data['trade_date'], recent_data['ma10'], label='MA10')
        plt.plot(recent_data['trade_date'], recent_data['ma20'], label='MA20')
        
        # 设置图表属性
        plt.title('价格走势图')
        plt.xlabel('日期')
        plt.ylabel('价格')
        plt.legend()
        plt.grid(True)
        plt.xticks(rotation=45)
        
        # 将图表转换为base64编码
        buffer = BytesIO()
        plt.savefig(buffer, format='png')
        buffer.seek(0)
        image_png = buffer.getvalue()
        buffer.close()
        plt.close()
        
        # 转换为base64字符串
        graphic = base64.b64encode(image_png).decode('utf-8')
        
        return graphic
    
    def generate_volume_chart(self, df, days=30):
        """生成成交量图表"""
        # 确保数据按日期排序
        df = df.sort_values('trade_date')
        
        # 获取最近days天的数据
        recent_data = df.iloc[-days:] if len(df) > days else df
        
        # 创建图表
        plt.figure(figsize=(10, 4))
        
        # 绘制成交量柱状图
        plt.bar(recent_data['trade_date'], recent_data['vol'], label='成交量')
        plt.plot(recent_data['trade_date'], recent_data['volume_ma5'], color='red', label='成交量MA5')
        
        # 设置图表属性
        plt.title('成交量图表')
        plt.xlabel('日期')
        plt.ylabel('成交量')
        plt.legend()
        plt.grid(True)
        plt.xticks(rotation=45)
        
        # 将图表转换为base64编码
        buffer = BytesIO()
        plt.savefig(buffer, format='png')
        buffer.seek(0)
        image_png = buffer.getvalue()
        buffer.close()
        plt.close()
        
        # 转换为base64字符串
        graphic = base64.b64encode(image_png).decode('utf-8')
        
        return graphic
    
    def generate_technical_chart(self, df, indicator, days=30):
        """生成技术指标图表"""
        # 确保数据按日期排序
        df = df.sort_values('trade_date')
        
        # 获取最近days天的数据
        recent_data = df.iloc[-days:] if len(df) > days else df
        
        # 创建图表
        plt.figure(figsize=(10, 4))
        
        if indicator == 'MACD':
            # 绘制MACD图表
            plt.plot(recent_data['trade_date'], recent_data['macd'], label='MACD')
            plt.plot(recent_data['trade_date'], recent_data['macd_signal'], label='Signal')
            plt.bar(recent_data['trade_date'], recent_data['macd_hist'], label='Histogram')
            plt.title('MACD指标')
        
        elif indicator == 'KDJ':
            # 绘制KDJ图表
            plt.plot(recent_data['trade_date'], recent_data['k'], label='K值')
            plt.plot(recent_data['trade_date'], recent_data['d'], label='D值')
            plt.plot(recent_data['trade_date'], recent_data['j'], label='J值')
            plt.title('KDJ指标')
        
        elif indicator == 'RSI':
            # 绘制RSI图表
            plt.plot(recent_data['trade_date'], recent_data['rsi'], label='RSI')
            plt.axhline(y=70, color='r', linestyle='-', label='超买线')
            plt.axhline(y=30, color='g', linestyle='-', label='超卖线')
            plt.title('RSI指标')
        
        elif indicator == 'BOLL':
            # 绘制布林带图表
            plt.plot(recent_data['trade_date'], recent_data['close'], label='收盘价')
            plt.plot(recent_data['trade_date'], recent_data['boll_upper'], label='上轨')
            plt.plot(recent_data['trade_date'], recent_data['boll_middle'], label='中轨')
            plt.plot(recent_data['trade_date'], recent_data['boll_lower'], label='下轨')
            plt.title('布林带指标')
        
        # 设置图表属性
        plt.xlabel('日期')
        plt.ylabel('值')
        plt.legend()
        plt.grid(True)
        plt.xticks(rotation=45)
        
        # 将图表转换为base64编码
        buffer = BytesIO()
        plt.savefig(buffer, format='png')
        buffer.seek(0)
        image_png = buffer.getvalue()
        buffer.close()
        plt.close()
        
        # 转换为base64字符串
        graphic = base64.b64encode(image_png).decode('utf-8')
        
        return graphic
    
    def generate_money_flow_chart(self, money_flow_df, days=10):
        """生成资金流向图表"""
        if money_flow_df.empty:
            return None
        
        # 确保数据按日期排序
        money_flow_df = money_flow_df.sort_values('trade_date')
        
        # 获取最近days天的数据
        recent_data = money_flow_df.iloc[-days:] if len(money_flow_df) > days else money_flow_df
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        
        # 绘制资金流向柱状图
        plt.bar(recent_data['trade_date'], recent_data['net_mf_amount'], label='净流入')
        
        # 设置图表属性
        plt.title('资金流向图表')
        plt.xlabel('日期')
        plt.ylabel('净流入金额（万元）')
        plt.legend()
        plt.grid(True)
        plt.xticks(rotation=45)
        
        # 将图表转换为base64编码
        buffer = BytesIO()
        plt.savefig(buffer, format='png')
        buffer.seek(0)
        image_png = buffer.getvalue()
        buffer.close()
        plt.close()
        
        # 转换为base64字符串
        graphic = base64.b64encode(image_png).decode('utf-8')
        
        return graphic
    
    def format_news(self, news_df, limit=5):
        """格式化新闻数据"""
        if news_df.empty:
            return [{'title': '无相关新闻', 'content': '暂无相关新闻数据', 'date': ''}]
        
        news_list = []
        for _, row in news_df.head(limit).iterrows():
            news_item = {
                'title': row['title'] if 'title' in row else '',
                'content': row['content'] if 'content' in row else '',
                'date': row['datetime'] if 'datetime' in row else ''
            }
            news_list.append(news_item)
        
        return news_list
    
    def generate_report(self, stock_code, stock_name, daily_data, index_data, money_flow_data, news_data, 
                        price_analysis, volume_analysis, tech_analysis, market_comparison, money_flow_analysis):
        """生成完整的复盘报告"""
        report = {
            'stock_code': stock_code,
            'stock_name': stock_name,
            'report_date': daily_data['trade_date'].iloc[-1] if not daily_data.empty else '',
            'price_chart': self.generate_price_chart(daily_data),
            'volume_chart': self.generate_volume_chart(daily_data),
            'macd_chart': self.generate_technical_chart(daily_data, 'MACD'),
            'kdj_chart': self.generate_technical_chart(daily_data, 'KDJ'),
            'rsi_chart': self.generate_technical_chart(daily_data, 'RSI'),
            'boll_chart': self.generate_technical_chart(daily_data, 'BOLL'),
            'money_flow_chart': self.generate_money_flow_chart(money_flow_data),
            'price_analysis': price_analysis,
            'volume_analysis': volume_analysis,
            'tech_analysis': tech_analysis,
            'market_comparison': market_comparison,
            'money_flow_analysis': money_flow_analysis,
            'news': self.format_news(news_data)
        }
        
        return report
    
    def generate_prediction_report(self, stock_code, stock_name, daily_data, predictions, support_resistance, trading_signal):
        """生成预测报告"""
        prediction_report = {
            'stock_code': stock_code,
            'stock_name': stock_name,
            'report_date': daily_data['trade_date'].iloc[-1] if not daily_data.empty else '',
            'price_chart': self.generate_price_chart(daily_data),
            'predictions': predictions,
            'support_resistance': support_resistance,
            'trading_signal': trading_signal
        }
        
        return prediction_report
    
    def save_report(self, report, filename):
        """保存报告到本地"""
        file_path = os.path.join(DATA_PATH, filename)
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                import json
                json.dump(report, f, ensure_ascii=False)
            return True
        except Exception as e:
            print(f"保存报告失败: {e}")
            return False